package cn.felord.security.autoconfigure.jwt;

import lombok.Data;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;

import java.io.Serializable;
import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 因为 {@link OAuth2AccessTokenResponse} 无法被序列化所以暂时以此类替换
 *
 * @author felord.cn
 * @since 2021 /4/13 13:15
 */
@Data
public class BearerTokenResponse implements Serializable {
    private static final long serialVersionUID = 3518818041598714076L;
    private AccessToken accessToken;

    private RefreshToken refreshToken;

    private Map<String, Object> additionalParameters;


    @Data
    public static class AccessToken {
        private String tokenValue;

        private Instant issuedAt;

        private Instant expiresAt;

        private Set<String> scopes;
    }

    @Data
    public static class RefreshToken {
        private String tokenValue;

        private Instant issuedAt;

        private Instant expiresAt;

    }

    /**
     * From token response.
     *
     * @param oAuth2AccessTokenResponse the o auth 2 access token response
     * @return the token response
     */
    public static BearerTokenResponse from(OAuth2AccessTokenResponse oAuth2AccessTokenResponse) {
        BearerTokenResponse bearerTokenResponse = new BearerTokenResponse();
        OAuth2AccessToken oAuth2AccessToken = oAuth2AccessTokenResponse.getAccessToken();
        AccessToken accessToken = new AccessToken();
        accessToken.setTokenValue(oAuth2AccessToken.getTokenValue());
        accessToken.setIssuedAt(oAuth2AccessToken.getIssuedAt());
        accessToken.setExpiresAt(oAuth2AccessToken.getExpiresAt());
        accessToken.setScopes(oAuth2AccessToken.getScopes());
        bearerTokenResponse.setAccessToken(accessToken);

        OAuth2RefreshToken oAuth2RefreshToken = oAuth2AccessTokenResponse.getRefreshToken();

        RefreshToken refreshToken = new RefreshToken();

        if (Objects.nonNull(oAuth2RefreshToken)) {
            refreshToken.setTokenValue(oAuth2RefreshToken.getTokenValue());
            refreshToken.setIssuedAt(oAuth2RefreshToken.getIssuedAt());
            refreshToken.setExpiresAt(oAuth2RefreshToken.getExpiresAt());
        }
        bearerTokenResponse.setRefreshToken(refreshToken);
        bearerTokenResponse.setAdditionalParameters(oAuth2AccessTokenResponse.getAdditionalParameters());
        return bearerTokenResponse;
    }

}
